package com.authine.cloudpivot.ext.utils;

import cn.hutool.core.util.NumberUtil;
import com.authine.cloudpivot.ext.enums.order.OrderGoodsStatusEnum;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

/**
 * @author Adam.yao
 * @date 2017/10/25
 */
public class BigDecimalUtils {
    private static final int DEF_DIV_SCALE = 10;

    private BigDecimalUtils() {
    }

    /**
     * 提供精确的加法运算。
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static BigDecimal add(BigDecimal v1, BigDecimal v2) {
        return v1.add(v2);
    }

    public static BigDecimal add(Object v1, Object v2) {
        return isNull(v1).add(isNull(v2));
    }

    /**
     * 提供精确的减法运算。
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static BigDecimal sub(BigDecimal v1, BigDecimal v2) {
        return v1.subtract(v2);
    }

    public static BigDecimal sub(Object v1, Object v2) {
        return sub(isNull(v1), isNull(v2));
    }

    /**
     * 提供精确的乘法运算。
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static BigDecimal mul(BigDecimal v1, BigDecimal v2) {
        return isNull(v1).multiply(isNull(v2));
    }

    public static BigDecimal mul(Object v1, Object v2) {
        return mul(isNull(v1), isNull(v2));
    }

    /**
     * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到 小数点以后10位，以后的数字四舍五入。
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static BigDecimal div(BigDecimal v1, BigDecimal v2) {
        return div(v1, v2, DEF_DIV_SCALE);
    }

    public static BigDecimal div(Object v1, Object v2) {
        return div(isNull(v1), isNull(v2));
    }

    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指 定精度，以后的数字四舍五入。
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */

    public static BigDecimal div(BigDecimal v1, BigDecimal v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        return v1.divide(v2, scale, RoundingMode.HALF_UP);
    }

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static BigDecimal round(BigDecimal v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal one = new BigDecimal("1");
        return v.divide(one, scale, RoundingMode.HALF_UP);
    }

    public static BigDecimal round(Object v, int scale) {
        return round(isNull(v), scale);
    }

    /**
     * 根据含税价 计算 税前金额
     *
     * @param taxAfter 含税价
     * @param rate     税率
     * @return taxBefore 税前价
     */
    public static BigDecimal calculateTaxBefore(BigDecimal taxAfter, BigDecimal rate) {
        BigDecimal rates = add(rate, new BigDecimal("1"));
        return BigDecimalUtils.div(taxAfter, rates, 11);
    }

    /**
     * 将Object转换为BigDecimal
     * @param bigDecimal
     * @param defaultValue 默认值
     * @return
     */
    public static BigDecimal isNull(Object bigDecimal, BigDecimal defaultValue) {
        if(Objects.isNull(bigDecimal)){
            return defaultValue;
        }
        if (bigDecimal instanceof BigDecimal) {
            return (BigDecimal) bigDecimal;
        }else if(bigDecimal instanceof Integer){
            return new BigDecimal(Integer.parseInt(String.valueOf(bigDecimal)));
        }else if(bigDecimal instanceof Double){
            return BigDecimal.valueOf(Double.parseDouble(String.valueOf(bigDecimal)));
        }else if(bigDecimal instanceof Float){
            return BigDecimal.valueOf(Float.parseFloat(String.valueOf(bigDecimal)));
        }else if(bigDecimal instanceof Long){
            return new BigDecimal(Long.parseLong(String.valueOf(bigDecimal)));
        }
        return defaultValue;
    }

    /**
     * 将Object转换为BigDecimal
     * @param bigDecimal
     * @return
     */
    public static BigDecimal isNull(Object bigDecimal) {
        return isNull(bigDecimal, new BigDecimal("0.0"));
    }

    /**
     * 将Integer转换为BigDecimal
     * @param integer
     * @return
     */
    public static BigDecimal integerToBigDecimal(Integer integer) {
        return isNull(new BigDecimal(integer), new BigDecimal("0.0"));
    }

    /**
     * 将object为Integer转换为BigDecimal
     * @param integer
     * @return
     */
    public static BigDecimal integerToBigDecimal(Object integer,BigDecimal defaultValue) {
        if(Objects.isNull(integer)){
            return defaultValue;
        }
        if (integer instanceof BigDecimal) {
            return isNull(integer,defaultValue);
        }else if(integer instanceof Integer){
            return isNull(new BigDecimal(Integer.parseInt(String.valueOf(integer))), defaultValue);
        }else if(integer instanceof Double){
            return isNull(new BigDecimal(Double.parseDouble(String.valueOf(integer))), defaultValue);
        }else if(integer instanceof Float){
            return isNull(new BigDecimal(Float.parseFloat(String.valueOf(integer))), defaultValue);
        }else if(integer instanceof Long){
            return isNull(new BigDecimal(Long.parseLong(String.valueOf(integer))), defaultValue);
        }
        return defaultValue;
    }

    /**
     * 将object为Integer转换为BigDecimal
     * @param integer
     * @return
     */
    public static BigDecimal integerToBigDecimal(Object integer) {
        return integerToBigDecimal(integer,new BigDecimal("0.0"));
    }

    public static Integer bigDecimalToInteger(Object bigDecimal,Integer defaultValue){
        if(Objects.isNull(bigDecimal)){
            return defaultValue;
        }
        if (bigDecimal instanceof BigDecimal) {
            BigDecimal b =new BigDecimal(String.valueOf(bigDecimal));
            return b.intValue();
        }else if(bigDecimal instanceof Integer){
            return Integer.parseInt(String.valueOf(bigDecimal));
        }else if(bigDecimal instanceof Double){
            Double d =Double.parseDouble(String.valueOf(bigDecimal));
            return d.intValue();
        }else if(bigDecimal instanceof Float){
            Float f = Float.parseFloat(String.valueOf(bigDecimal));
            return f.intValue();
        }else if(bigDecimal instanceof Long){
            Long l = Long.parseLong(String.valueOf(bigDecimal));
            return l.intValue();
        }else if(bigDecimal instanceof String){
            return Integer.parseInt(String.valueOf(bigDecimal));
        }
        return defaultValue;
    }

    public static Integer bigDecimalToInteger(Object integer){
        return bigDecimalToInteger(integer,null);
    }

    public static void main(String[] args) {
        BigDecimal deliverableNum = new BigDecimal("0.00000000000000000000000000");
        System.out.println(deliverableNum.compareTo(BigDecimal.ZERO) != 1);
    }
}
